use serde::Deserialize;
use std::path::Path;
use anyhow::Context;
use std::fs;

#[derive(Debug, Deserialize)]
pub struct ServerConfig {
    pub port: u16,
    pub host: String,
    pub workers: usize,
}

#[derive(Debug, Deserialize)]
pub struct DatabaseConfig {
    pub redis_url: String,
    pub sqlite_path: String,
}

#[derive(Debug, Deserialize)]
pub struct AuthConfig {
    pub jwt_secret: String,
    pub token_expiry: u64,
}

#[derive(Debug, Deserialize, Clone)]
pub struct IpAuthConfig {
    pub enabled: bool,
    pub mode: String,
    pub whitelist: Vec<String>,
    pub blacklist: Vec<String>,
    pub max_requests_per_minute: u32,
}

#[derive(Debug, Deserialize, Clone)]
pub struct LoggingConfig {
    pub level: String,
    pub file_path: Option<String>,
    pub max_files: usize,
    pub max_file_size: u64,
    pub enable_console: bool,
}

#[derive(Debug, Deserialize)]
pub struct AppConfig {
    pub server: ServerConfig,
    pub database: DatabaseConfig,
    pub auth: AuthConfig,
    pub ip_auth: IpAuthConfig,
    pub logging: LoggingConfig,
}

impl Default for AppConfig {
    fn default() -> Self {
        Self {
            server: ServerConfig {
                port: 8080,
                host: "0.0.0.0".to_string(),
                workers: 4,
            },
            database: DatabaseConfig {
                redis_url: "redis://localhost:6379".to_string(),
                sqlite_path: "gateway.db".to_string(),
            },
            auth: AuthConfig {
                jwt_secret: "your-secret-key-change-in-production".to_string(),
                token_expiry: 3600,
            },
            ip_auth: IpAuthConfig {
                enabled: true,
                mode: "mixed".to_string(),
                whitelist: vec![
                    "127.0.0.1".to_string(),
                    "::1".to_string(),
                    "192.168.1.0/24".to_string(),
                ],
                blacklist: vec![],
                max_requests_per_minute: 1000,
            },
            logging: LoggingConfig {
                level: "info".to_string(),
                file_path: Some("logs".to_string()),
                max_files: 10,
                max_file_size: 100 * 1024 * 1024,
                enable_console: true,
            },
        }
    }
}

impl AppConfig {
    pub fn load() -> anyhow::Result<Self> {
        Self::load_from_file("config/config.yaml")
    }
    
    pub fn load_from_file<P: AsRef<Path>>(path: P) -> anyhow::Result<Self> {
        let path = path.as_ref();
        
        // 如果配置文件不存在，使用默认配置
        if !path.exists() {
            println!("⚠️  配置文件不存在: {:?}，使用默认配置", path);
            return Ok(AppConfig::default());
        }
        
        // 读取并解析 YAML 配置文件
        let content = fs::read_to_string(path)
            .with_context(|| format!("无法读取配置文件: {:?}", path))?;
        
        let config: AppConfig = serde_yaml::from_str(&content)
            .with_context(|| format!("配置文件格式错误: {:?}", path))?;
        
        println!("✅ 配置文件加载成功: {:?}", path);
        Ok(config)
    }
}

pub fn load_config() -> anyhow::Result<AppConfig> {
    AppConfig::load()
}